/*
 * <Pezad Platformer>
 * Copyright 2008 Shayne Riley
 * 
 * This file is part of <Pezad Platformer>.
 * 
 * <Pezad Platformer> is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * <Pezad Platformer> is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with <Pezad Platformer>.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * To contact the authors on questions or issues regarding the license,
 * you may send an email to <shayner@gmail.com> or write to
 * Shayne Riley / P.O. Box 1092 / McCook, NE 69001.
 */

#include "Game.h"
#include <SDL/SDL.h> // <-- This better be temporary! Arg! No wantee SDL here!
#include "ResLoader.h"
#include "ImageSDL.h"
#include "Display.h"
#include "Control.h"
#include "Audio.h"
#include <iostream>

namespace pzdLogic
{

Game::Game()	
{
    init();
}

Game::~Game()
{
    finalize();
}

void Game::finalize()
{
	// Does nothing. Yet.
}

void Game::init()
{
	// Does nothing. Yet.
}

void Game::playGame()
{
	using namespace std;
	using namespace pzdUtil;
	using namespace pzdDisplay;
	using namespace pzdControl;
	using namespace pzdAudio;

	ResLoader loader;

// TODO This function has become a God Function. Delegate these pre-game tasks
//	to some other function, which calls the functions to load each system.

	// The ImageSDL needs to handle copies and assignments. Right now, it is
	// one big memory leak waiting to happen.
	background = loader.readImage("res/image/background.bmp");
	actor = loader.readImage("res/image/avatar.bmp");

//	Display display;

	display.setBackground(background);
	display.setActor(actor);

	Control& control = Control::getInstance();
	control.addInputHandler(movement);

	Audio& audio = Audio::getInstance();
	
	// TODO add a check to make sure that audio systems are good to go.
	
	bool playableAudio = audio.loadAudio("res/audio/cannon.wav");
	if(playableAudio)
	{
		audio.playAudio();
	}
	bool playableBGM = audio.loadBGM("res/audio/audio.ogg");
	if(playableBGM)
	{
		audio.playBGM();
	}
	

	// If this is true, the game can still be played.
	bool play = true;

	Uint32 renderTimeStart = SDL_GetTicks();
	Uint32 renderTimeEnd = renderTimeStart;
	bool limitFPS = true;
	Uint16 maxFPS = 60;
	Uint32 millisecondsPerFrame = 1000/maxFPS;

	Uint32 longTimeStart = SDL_GetTicks();
	Uint16 frameCount = 0;

	while(play)
	{
		display.doFrame();

		doMovementStuff();
		play = !movement.quit();

		renderTimeEnd = SDL_GetTicks();
		// No intense game stuff after this point, please.

		if(limitFPS)
		{
			Uint32 totalRenderTime = renderTimeEnd-renderTimeStart;
			if(totalRenderTime < millisecondsPerFrame)
			{
				SDL_Delay(millisecondsPerFrame-totalRenderTime);
			}
		}

		// This is actually a somewhat silly way of counting frames. Simple
		// Dividing each frame would work just as easily.
		++frameCount;
		if(renderTimeEnd - longTimeStart >= 1000)
		{
			cout << "Frame count: " << frameCount << endl;
			frameCount = 0;
			longTimeStart = renderTimeEnd;
		}

		// the end time is assigned to the start time to account for the
		// frame limiting in the middle, instead of grabbing the ticks again.
		renderTimeStart = renderTimeEnd;		
	}
	delete background;
	delete actor;
	cout << "Done!" << endl;
}

void Game::doMovementStuff()
{
	static int x = 296, y = 233;

	if(movement.moveRight())
	{
		x += 1;

		display.setActorPos(x, y); // This is not thread-safe, methinks.
	}

	if(movement.moveLeft())
	{
		x -= 1;

		display.setActorPos(x, y); // This is not thread-safe, methinks.
	}

	if(movement.makeNoise())
	{
		pzdAudio::Audio& audio = pzdAudio::Audio::getInstance();
		audio.playAudio();
	}
}

} // namespace
